package com.kingdee.eas.custom.tiog.connector.util;

import org.apache.commons.lang.StringUtils;

import java.io.*;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * @author Jambin
 * @copyright 天津金蝶软件有限公司
 * @description zip压缩解压工具类
 * @date Created in 2020/3/20
 */

public class FileZipUtil {

    /**
     * zip文件压缩
     *
     * @param inputFile  待压缩文件夹/文件名
     * @param outputFile 生成的压缩包名字
     */

    public static void ZipCompress(String inputFile, String outputFile) throws Exception {
        //创建zip输出流
        ZipOutputStream out = new ZipOutputStream(new FileOutputStream(outputFile));
        //创建缓冲输出流
        BufferedOutputStream bos = new BufferedOutputStream(out);
        File input = new File(inputFile);
        compress(out, bos, input, null);
        bos.close();
        out.close();
    }

    /**
     * @param name 压缩文件名，可以写为null保持默认
     */
    //递归压缩
    public static void compress(ZipOutputStream out, BufferedOutputStream bos, File input, String name) throws IOException {
        if (name == null) {
            name = input.getName();
        }
        //如果路径为目录（文件夹）
        if (input.isDirectory()) {
            //取出文件夹中的文件（或子文件夹）
            File[] flist = input.listFiles();

            if (flist.length == 0)//如果文件夹为空，则只需在目的地zip文件中写入一个目录进入
            {
                out.putNextEntry(new ZipEntry(name + "/"));
            } else//如果文件夹不为空，则递归调用compress，文件夹中的每一个文件（或文件夹）进行压缩
            {
                for (int i = 0; i < flist.length; i++) {
                    compress(out, bos, flist[i], name + "/" + flist[i].getName());
                }
            }
        } else//如果不是目录（文件夹），即为文件，则先写入目录进入点，之后将文件写入zip文件中
        {
            out.putNextEntry(new ZipEntry(name));
            FileInputStream fos = new FileInputStream(input);
            BufferedInputStream bis = new BufferedInputStream(fos);
            int len = -1;
            //将源文件写入到zip文件中
            byte[] buf = new byte[1024];
            while ((len = bis.read(buf)) != -1) {
                bos.write(buf, 0, len);
            }
            bis.close();
            fos.close();
        }
    }

    /**
     * zip解压
     *
     * @param inputFile   待解压文件名
     * @param destDirPath 解压路径
     */

    public static void ZipUncompress(String inputFile, String destDirPath) throws Exception {
        File srcFile = new File(inputFile);//获取当前压缩文件
        // 判断源文件是否存在
        if (!srcFile.exists()) {
            throw new Exception(srcFile.getPath() + "所指文件不存在");
        }
        //开始解压
        //构建解压输入流
        ZipInputStream zIn = new ZipInputStream(new FileInputStream(srcFile));
        ZipEntry entry = null;
        File file = null;
        while ((entry = zIn.getNextEntry()) != null) {
            if (!entry.isDirectory()) {
                file = new File(destDirPath, entry.getName());
                if (!file.exists()) {
                    new File(file.getParent()).mkdirs();//创建此文件的上级目录
                }
                OutputStream out = new FileOutputStream(file);
                BufferedOutputStream bos = new BufferedOutputStream(out);
                int len = -1;
                byte[] buf = new byte[1024];
                while ((len = zIn.read(buf)) != -1) {
                    bos.write(buf, 0, len);
                }
                // 关流顺序，先打开的后关闭
                bos.close();
                out.close();
            }
        }
    }

    /**
     * @param inputStream 要解析的文件流
     * @param fileType    要解析的文件类型
     * @return java.lang.String 文件内容
     * @title readZipFromInputStream
     * @description 直接从文件流解析zip文件
     * @author Jambin
     * @date 2020/3/19
     */
    public static Map<String, String> readZipFromInputStream(InputStream inputStream, String fileType) {
        //获取文件类型，为空时默认读取.xml文件
        if (StringUtils.isBlank(fileType)) {
            fileType = ".xml";
        }

        Map<String, String> contentMap = new HashMap<String, String>();
        ZipInputStream zipInputStream = null;
        BufferedReader bufferedReader = null;
        //定义ZipEntry置为null,避免由于重复调用zipInputStream.getNextEntry造成的不必要的问题
        ZipEntry zipEntry = null;

        try {
            //获取ZIP输入流(一定要指定字符集Charset.forName("GBK")否则会报java.lang.IllegalArgumentException: MALFORMED)
            zipInputStream = new ZipInputStream(new BufferedInputStream(inputStream));
            //遍历
            while ((zipEntry = zipInputStream.getNextEntry()) != null) {
                if (zipEntry.toString().endsWith(fileType)) {
                    System.out.println("正在解析的文件为：" + zipEntry.getName() + ",文件大小：" + zipEntry.getSize());
                    StringBuffer fileContent = new StringBuffer();
                    //读取
                    bufferedReader = new BufferedReader(new InputStreamReader(zipInputStream));
                    String line;
                    //内容不为空
                    while ((line = bufferedReader.readLine()) != null) {
                        fileContent.append(line);
                    }
                    contentMap.put(zipEntry.getName(), fileContent.toString());
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } finally {
            //关闭流
            try {
                bufferedReader.close();
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }
        return contentMap;
    }

    /**
     * @param file     要解析的文件
     * @param fileType 要解析的文件类型
     * @return java.lang.String 文件内容
     * @title readZipFromFile
     * @description 从指定zip文件中解析
     * @author Jambin
     * @date 2020/3/19
     */
    public static String readZipFromFile(File file, String fileType) {
        //获取文件类型，为空时默认读取.xml文件
        if (StringUtils.isBlank(fileType)) {
            fileType = ".xml";
        }

        StringBuffer fileContent = new StringBuffer();
        ZipFile zip = null;
        InputStream inputStream = null;
        BufferedReader bufferedReader = null;

        try {
            zip = new ZipFile(file);
            Enumeration zipEnumeration = zip.entries();
            //遍历获取内容
            while (zipEnumeration.hasMoreElements()) {
                ZipEntry zipEntry = (ZipEntry) zipEnumeration.nextElement();
                //当文件时要读取的类型时
                if (zipEntry.toString().endsWith(fileType)) {
                    System.out.println("正在解析的文件为：" + zipEntry.getName() + ", 文件大小：" + zipEntry.getSize());
                    inputStream = zip.getInputStream(zipEntry);
                    bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
                    String line;
                    //内容不为空
                    while ((line = bufferedReader.readLine()) != null) {
                        fileContent.append(line);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } finally {
            try {
                //关闭流
                bufferedReader.close();
                inputStream.close();
                zip.close();
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }
        return fileContent.toString();
    }


}

